import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios';
import router from '../router'
import { systemConfig } from '../library/config'
import { getToken, delToken } from '../library/cookieUtil'
import { layer } from '@layui/layui-vue';

type TAxiosOption = {
    timeout: number;
    baseURL: string;
}

const config: TAxiosOption = {
    timeout: 5000,
    baseURL: systemConfig.apiURL
}

const codeMessage = {
    200: '请求成功',
    401: '没有权限',
    403: '访问被禁止',
    404: '请求内容不存在',
    500: '服务器错误',
}

const clearAccessTokens = () => {
    delToken()
    window.location.reload();
};
class Http {
    service;
    constructor(config: TAxiosOption) {
        this.service = axios.create(config)
        /* 请求拦截 */
        this.service.interceptors.request.use((config: AxiosRequestConfig) => {
            const token = getToken();
            if (token)
                (config.headers as AxiosRequestHeaders).Authorization = 'Bearer ' + token as string
            else
                if (router.currentRoute.value.path !== '/login') router.replace('/login');
            return config
        }, error => {
            return Promise.reject(error);
        })
        // 响应拦截
        this.service.interceptors.response.use(
            (response: AxiosResponse<any>) => {
                var serve = response.data;
                if (serve.status === 401) {
                    clearAccessTokens();
                } else if (serve.status === undefined) {
                    return Promise.resolve(response);
                } 
                else if (serve.status !== 1) {
                    var message = JSON.stringify(serve.msg);
                    layer.msg(message, { time: 2000, icon: 2 })
                    throw new Error(message);
                }
                return response.data
            },
            err => {
                if (err.response) {
                    let data = err.response
                    let description
                    switch (data.status) {
                        case 401:
                            clearAccessTokens();
                            break
                        case 403:
                            router.replace({ path: '/error/403' });
                            description = data.Message || codeMessage[403]
                            break
                        case 404:
                            router.replace({ path: '/error/404' });
                            description = data.Message || codeMessage[404]
                            break
                        case 500:
                            router.replace({ path: '/error/500' });
                            description = data.Message || codeMessage[500]
                            break
                        default:
                            description = data.Message || '未知错误 ' + err.response.status
                            data.url && router.replace(data.url)
                    }
                }

                if (err.message.indexOf('timeout') != -1) {
                    layer.notifiy({title: "网络超时",time: 5000,})
                } else if (err.message == 'Network Error') {
                    layer.notifiy({title: "网络连接错误",time: 5000,icon:2})
                } else {
                    if (err.response.data)
                        layer.notifiy({title: "网络错误",time: 5000,content: err.response.statusText})
                    else 
                        layer.notifiy({title: "接口路径找不到",time: 5000,})
                }
                return Promise.reject(err);
            })
    }

    /* GET 方法 */
    get<T>(url: string, params?: object, _object = {}): Promise<any> {
        return this.service.get(url, { params, ..._object })
    }
    /* POST 方法 */
    post<T>(url: string, params?: object, _object = {}): Promise<any> {
        return this.service.post(url, params, _object)
    }
    /* PUT 方法 */
    put<T>(url: string, params?: object, _object = {}): Promise<any> {
        return this.service.put(url, params, _object)
    }
    /* DELETE 方法 */
    delete<T>(url: string, params?: any, _object = {}): Promise<any> {
        return this.service.delete(url, { params, ..._object })
    }
}

export default new Http(config)
